use std::error::Error;

use super::{cmd::Command, SidecarInBoundChain, SidecarInBoundPort, SidecarOutBoundChain, DefaultSidecarUid, SidecarOutBoundPort};


pub fn add_all_rules<I>(inbound_ignore_port:I) -> Result<(),Box<dyn Error>>
    where I:IntoIterator<Item=i32>
{
    let c = Command::new();
    c.args(["iptables","-t","nat","-N",SidecarInBoundChain]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-N",SidecarOutBoundChain]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A","PREROUTING","-p","tcp","-j",SidecarInBoundChain]).run()?;

    for port in inbound_ignore_port {
        let p = port.to_string();
        let str = p.as_str();
        let c = Command::new();
        c.args(["iptables","-t","nat","-A",SidecarInBoundChain,"-p","tcp","-m","tcp","--dport",str,"-j","RETURN"]).run()?;    
    }
   
    let c = Command::new();
    c.args(["iptables","-t","nat","-A",SidecarInBoundChain,"-d","127.0.0.1/32","-j","RETURN"]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A",SidecarInBoundChain,"-p","tcp","-m","tcp","-j","REDIRECT","--to-port",SidecarInBoundPort]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A","OUTPUT","-p","tcp","-j",SidecarOutBoundChain]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A",SidecarOutBoundChain,"-d","127.0.0.1/32","-j","RETURN"]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A",SidecarOutBoundChain,"!", "-d", "127.0.0.1/32", "-m", "owner", "--uid-owner", DefaultSidecarUid, "-j", "RETURN"]).run()?;

    let c = Command::new();
    c.args(["iptables","-t","nat","-A",SidecarOutBoundChain,"-p", "tcp", "-m", "tcp", "-j", "REDIRECT", "--to-port",SidecarOutBoundPort]).run()?;

    Ok(())
}